// LabelConfig.js
class LabelConfig {
    constructor() {
        // 获取数据集信息
        this.dataset_id = null;
        this.dataset_type = null;
        this.label_format = null;

        // 定义一些通用配置信息
        this.base_config = {
            rect_style: {
                fill: 'rgba(0,0,0,0)',
                strokeWidth: 2,
                stroke: 'rgba(0,200,0,1.0)',
                visible: true
            },
            polygon_style: {
                fill: 'rgba(0,0,200,0.4)',
                strokeWidth: 1,
                stroke: 'rgba(0,0,200,1.0)',
                visible: true
            },
            keypoint: {
                radius: 3,
                visibleFill: '#FF3B30', // v=2时的颜色
                occludedFill: '#FFAA30', // v=1时的颜色
                hiddenFill: 'transparent', // v=0时不显示
                stroke: '#FFFFFF',
                strokeWidth: 1
            },
            skeleton: {
                stroke: {
                    default: '#58A55C',
                    // 可定义不同连接的特定颜色（基于COCO骨架）
                    '12-11': '#FF0000' // 示例：特定连接颜色
                },
                strokeWidth: 2,
                lineDash: null
            },
            keypoints_back: {
                fill: 'rgba(0, 0, 255, 0.05)', // 半透明蓝色背景
                stroke: 'transparent', // 隐藏边框
                strokeWidth: 0,         // 设置边框宽度为0
            },
            evaluation: {
                tp_rect_style: {
                    fill: 'rgba(0,0,0,0)',
                    strokeWidth: 3,
                    stroke: 'rgba(0,200,0,1.0)',
                    visible: true
                },
                fp_rect_style: {
                    fill: 'rgba(0,0,0,0)',
                    strokeWidth: 3,
                    stroke: 'rgba(200,0,0,1.0)',
                    visible: true
                },
                fn_rect_style: {
                    fill: 'rgba(0,0,0,0)',
                    strokeWidth: 3,
                    stroke: 'rgba(200,0,0,1.0)',
                    visible: true
                }
            }
        };

        // 定义一些和dataset_type、label_format相关的配置信息
        this.dataset_config = {
            detection: {
                coco: {
                    tools: ['pointer', 'rect', 'poly', 'predata', 'nextdata', 'deletedata', 'settings']
                },
                voc: {
                    tools: ['pointer', 'rect', 'predata', 'nextdata', 'deletedata', 'settings']
                },
                yolo: {
                    tools: ['pointer', 'rect', 'predata', 'nextdata', 'deletedata', 'settings']
                }
            },
            keypoint: {
                coco: {
                    tools: ['pointer', 'rect', 'predata', 'nextdata', 'deletedata', 'settings']
                }
            },
            caption: {
                coco: {
                    tools: ['pointer', 'predata', 'nextdata', 'deletedata']
                }
            },
            ocr: {
                paddle: {
                    tools: ['pointer', 'rect', 'poly', 'predata', 'nextdata', 'deletedata']
                }
            }
        };

        // 定义一些工具相关的配置
        this.shortcuts_config = {
            'ctrl+shift+x': [
                {
                    vue: 'App',
                    method: 'toggleConsole',
                    params: []
                }
            ],
            'ctrl+delete': [
                {
                    vue: 'ToolPanel',
                    method: 'deleteLabelData',
                    params: []
                }
            ],
            'ctrl+backspace': [
                {
                    vue: 'ToolPanel',
                    method: 'deleteLabelData',
                    params: []
                }
            ],
            m: [
                {
                    vue: 'App',
                    method: 'toggleRemoteList',
                    params: []
                }
            ],
            delete: [
                {
                    vue: 'ToolPanel',
                    method: 'deleteSelection',
                    params: []
                }
            ],
            backspace: [
                {
                    vue: 'ToolPanel',
                    method: 'deleteSelection',
                    params: []
                }
            ],
            escape: [
                {
                    vue: 'GridPanel',
                    method: 'closePreview',
                    params: []
                }
            ],
            arrowleft: [
                {
                    vue: 'ToolPanel',
                    method: 'preLabelData',
                    params: []
                },
                {
                    vue: 'GridPanel',
                    method: 'preLabelData',
                    params: []
                },
                {
                    vue: 'EvalPanel',
                    method: 'preLabelData',
                    params: []
                }
            ],
            arrowright: [
                {
                    vue: 'ToolPanel',
                    method: 'nextLabelData',
                    params: []
                },
                {
                    vue: 'GridPanel',
                    method: 'nextLabelData',
                    params: []
                },
                {
                    vue: 'EvalPanel',
                    method: 'nextLabelData',
                    params: []
                }
            ],
            a: [
                {
                    vue: 'ToolPanel',
                    method: 'preLabelData',
                    params: []
                },
                {
                    vue: 'GridPanel',
                    method: 'preLabelData',
                    params: []
                },
                {
                    vue: 'EvalPanel',
                    method: 'preLabelData',
                    params: []
                }
            ],
            d: [
                {
                    vue: 'ToolPanel',
                    method: 'nextLabelData',
                    params: []
                },
                {
                    vue: 'GridPanel',
                    method: 'nextLabelData',
                    params: []
                },
                {
                    vue: 'EvalPanel',
                    method: 'nextLabelData',
                    params: []
                }
            ],
            s: [
                {
                    vue: 'ImageRegion',
                    method: 'clickLabelTool',
                    params: ['pointer']
                }
            ],
            r: [
                {
                    vue: 'ImageRegion',
                    method: 'clickLabelTool',
                    params: ['rect']
                }
            ],
            w: [
                {
                    vue: 'ImageRegion',
                    method: 'clickLabelTool',
                    params: ['poly']
                }
            ]
        };

        // 定义dataset_id相关的独有配置
        this.custom_config = {};
    }

    setDatasetInfo(dataset_info) {
        // console.log(dataset_info);
        this.dataset_id = dataset_info.id;
        this.dataset_type = dataset_info.dataset_type;
        this.label_format = dataset_info.label_format;
    }

    setConfig(dataset_id, key, value) {
        // console.log(dataset_id);
        if (!this.custom_config[dataset_id]) {
            this.custom_config[dataset_id] = {};
        }
        // 实现key的解析和赋值
        const tokens = key.split('.');
        let current = this.custom_config[dataset_id];
        for (let i = 0; i < tokens.length - 1; i++) {
            if (!(tokens[i] in current)) {
                current[tokens[i]] = {};
            }
            current = current[tokens[i]];
        }
        current[tokens[tokens.length - 1]] = value;
    }

    getConfig(key) {
        // console.log(`getConfig key = `, key);
        let config = {};
        Object.assign(config, this.base_config);

        // 先尝试自定义配置的读取
        let dataset_id = this.dataset_id;
        // console.log(`dataset_id = ${dataset_id}, `, this.custom_config[dataset_id]);
        if (dataset_id && this.custom_config[dataset_id]) {
            this.mergeConfig(config, this.custom_config[dataset_id]);
        }

        // 如果存在dataset_id，则读取对应的dataset配置
        if (this.dataset_type && this.label_format) {
            try {
                // console.log(`dataset_type = ${this.dataset_type}, label_format = ${this.label_format}`);
                Object.assign(config, this.dataset_config[this.dataset_type][this.label_format]);
            } catch (error) {
                console.error(error);
            }
        }

        let result = config;
        if (key) {
            const tokens = key.split(/\.|\//);
            result = tokens.reduce((o, k) => (o || {})[k], config);
        }
        return result;
    }

    // 递归合并两个配置对象
    mergeConfig(target, source) {
        for (let key of Object.keys(source)) {
            if (source[key] instanceof Object && key in target) {
                this.mergeConfig(target[key], source[key]);
            } else {
                target[key] = source[key];
            }
        }
    }

    getShortcuts(name, combinedKey) {
        // console.log(`getShortcuts name = ${name}, combinedKey = `, combinedKey);
        if (combinedKey in this.shortcuts_config) {
            const shortcutEntries = this.shortcuts_config[combinedKey];
            const matchedShortcut = shortcutEntries.find((item) => {
                return item.vue === name;
            });
            return matchedShortcut;
        } else {
            return {};
        }
    }

    runShortCuts(name, methods, event) {
        let key = event.key.toLowerCase();
        const combinedKey = [event.ctrlKey ? 'ctrl' : '', event.shiftKey ? 'shift' : '', event.altKey ? 'alt' : '', event.metaKey ? 'meta' : '', key].filter(Boolean).join('+');
        const shortcut = this.getShortcuts(name, combinedKey);
        if (shortcut && methods && methods[shortcut.method]) {
            methods[shortcut.method](...shortcut.params);
        }
    }
}

export default new LabelConfig();
